﻿using System;
using System.Reflection;
using System.Windows.Input;
using Plugins.UserControls;
using StockModel;
using Utils.Wpf;

namespace FullDayStrategyPlugin.Realtime
{
	internal class ControlPanelVM : ViewModelBase, IDisposable
	{
		#region Attributes

		private readonly EngineSettings _settings;
		private readonly Engine _engine;

		private bool _isRunning;

		#endregion

		#region Properties

		public bool IsRunning
		{
			get
			{
				return _isRunning;
			}
			set
			{
				if (_isRunning != value)
				{
					_isRunning = value;
					base.OnPropertyChanged("IsRunning");
				}
			}
		}

		public ICommand RunStrategyCommand { get; private set; }
		public ICommand StopStrategyCommand { get; private set; }

		public PresetSelectorVM<EngineSettings> PresetSelectorVM { get; private set; }
		public StockSelectorVM StockSelectorVM { get; private set; }
		public HourSelectorVM HourSelectorVM { get; private set; }
		public StrategyControlVM StrategyControlVM { get; private set; }
		public InternalStateVM InternalStateVM { get; private set; }
		public StockParametersSelectorVM StockParametersSelectorVM { get; private set; }

		#endregion

		#region Public Methods

		public ControlPanelVM(RawStockDataSource rawStockDataSource, Engine engine, DecisionEngineData engineData, DecisionEngineDataSource engineDataSource)
		{
			_engine = engine;

			this.RunStrategyCommand = new DelegateCommand(ExecuteRunStrategy, CanRunStrategy);
			this.StopStrategyCommand = new DelegateCommand(ExecuteStopStrategy, CanStopStrategy);

            this.StockSelectorVM = new StockSelectorVM(rawStockDataSource);
            this.HourSelectorVM = new HourSelectorVM();
			this.StrategyControlVM = new StrategyControlVM();
			this.StockParametersSelectorVM = new StockParametersSelectorVM();

			// Create settings
			_settings = new EngineSettings(this.StockSelectorVM.Data, this.HourSelectorVM.Data, this.StrategyControlVM.Data, this.StockParametersSelectorVM.Data);
			_engine.Settings = _settings;

			// Set default values to avoid warnings
			_settings.StartWithOpening = true;
			_settings.QuantityToBuy = 1;
			_settings.ValueMultiplier = 1;

			this.PresetSelectorVM = new PresetSelectorVM<EngineSettings>(Assembly.GetExecutingAssembly().GetName().Name + Properties.Settings.Default.RealtimePresetsFilename, _settings);
			this.InternalStateVM = new InternalStateVM(engineData, engineDataSource);
		}

		#endregion

		#region Private Methods

		private void ExecuteRunStrategy()
		{
			_engine.Start();
			this.IsRunning = _engine.IsStarted;
		}

		private bool CanRunStrategy()
		{
			return !this.StrategyControlVM.HasValidationErrors && !this.InternalStateVM.HasValidationErrors && !this.HourSelectorVM.HasValidationErrors && this.StockSelectorVM.IsStockSelected && !this.StockParametersSelectorVM.HasValidationErrors && !this.IsRunning;
		}

		private void ExecuteStopStrategy()
		{
			_engine.Stop();
			this.IsRunning = _engine.IsStarted;
		}

		private bool CanStopStrategy()
		{
			return !this.StrategyControlVM.HasValidationErrors && !this.InternalStateVM.HasValidationErrors && !this.HourSelectorVM.HasValidationErrors && this.StockSelectorVM.IsStockSelected && !this.StockParametersSelectorVM.HasValidationErrors && this.IsRunning;
		}

		#endregion

		#region IDisposable

		protected bool Disposed { get; private set; }

		private void Dispose(bool disposing)
		{
			if (!this.Disposed)
			{
				this.InternalDispose(disposing);
			}

			this.Disposed = true;
		}

		protected virtual void InternalDispose(bool disposing)
		{
			if (disposing)
			{
				this.InternalStateVM.Dispose();
			}

			// Dispose here only unmanaged objects 
			// Don’t use managed objects here because maybe 
			// they have been finalized already
		}

		public void Dispose()
		{
			this.Dispose(true);
			GC.SuppressFinalize(this);
		}

		~ControlPanelVM()
		{
			this.Dispose(false);
		}

		#endregion
	}
}
